package org.kitrum.example.asm;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

/**
 * @program: kitrum-example
 * @description:
 * @author: Kun
 * @create: 2021-01-25 13:40
 */
public class HalloWorldAsm extends ClassLoader implements Opcodes {

    public static void main(String[] args) throws IOException, InvocationTargetException, IllegalAccessException {
        ClassWriter classWriter = new ClassWriter(0);
        classWriter.visit(V1_1,ACC_PUBLIC,"Example",null,"java/lang/Object",null);
        MethodVisitor methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
        methodVisitor.visitVarInsn(ALOAD,0);
        methodVisitor.visitMethodInsn(INVOKESPECIAL,"java/lang/Object","<init>","()V");
        methodVisitor.visitInsn(RETURN);
        methodVisitor.visitMaxs(1,1);
        methodVisitor.visitEnd();
        methodVisitor = classWriter.visitMethod(ACC_PUBLIC + ACC_STATIC, "main",
            "([Ljava/lang/String;)V", null, null);
        methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
            "Ljava/io/PrintStream;");
        methodVisitor.visitLdcInsn("Hello world!");
        methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
            "(Ljava/lang/String;)V");
        methodVisitor.visitInsn(RETURN);
        methodVisitor.visitMaxs(2, 2);
        methodVisitor.visitEnd();
        byte[] code = classWriter.toByteArray();
        FileOutputStream fos = new FileOutputStream("Example.class");
        fos.write(code);
        fos.close();
        HalloWorldAsm loader = new HalloWorldAsm();
        Class exampleClass = loader
            .defineClass("Example", code, 0, code.length);
        exampleClass.getMethods()[0].invoke(null, new Object[]{null});
    }
}
